/*eslint-disable*/
import React from 'react';
import G6 from '@antv/g6';

import styles from './index.module.less';

let graph;
let addingEdge = false;
let edge;
let sourceId;

const PlayGraph = ({
  task,
  id,
  disable,
  setGraphAction,
  setVisible,
  setNodeInfo,
  setEdgesInfo,
  handleDragNode,
}) => {
  // const [data, setData] = React.useState(task ? { nodes: task.nodes, edges: task.edges } : { nodes: [], edges: [] });
  const data = {
    nodes: [],
    edges: [],
  };

  const Ref = React.useRef({});

  const handleNodeClick = (nodeInfo) => {
    setVisible(true);
    setNodeInfo(nodeInfo._cfg)
  };

  const handleEdges = () => {
    const { edges } = graph.save();
    setEdgesInfo(edges);
  };

  const addAnchor = (group, x, y, nodeId, anchorIndex) => {
    const anchor = group.addShape('circle', {
      attrs: {
        x, // 必须配置 
        y, // 必须配置
        fill: '#5E728C',
        stroke: '#5E728C',
        opacity: 1,
        r: 5,
        cursor: 'pointer',
      },
      name: 'circle-shape',
      capture: true,
      zIndex: 100,
      draggable: true,
      // ...其他属性
    })
    // 这里支持所有鼠标事件, 键盘事件等
    anchor.on('click', (evt) => {
      // 鼠标当前点击的节点的位置
      const point = graph.getPointByCanvas(evt.x, evt.y);
      // const model = node.getModel();
      if (addingEdge && edge) {
        const isSwitchNode = edge._cfg.source._cfg.currentShape === 'diamond';
        const edgeConfig = isSwitchNode ? {
          target: nodeId,
          targetAnchor: anchorIndex,
          label: edge._cfg.model.sourceAnchor === 1 ? 'yes' : 'no',
          labelCfg: {
            style: {
              fontSize: 14,
              fill: '#E7EFFF'
            }
          },
        }
          : {
            target: nodeId,
            targetAnchor: anchorIndex,
          }
        // 如果起始点不等于当前点
        if (sourceId !== nodeId) {
          graph.updateItem(edge, edgeConfig);
          edge = null;
          addingEdge = false;
          handleEdges();
        }
      } else {
        // 在图上新增一条边，结束点是鼠标当前点击的节点的位置
        edge = graph.addItem('edge', {
          source: nodeId,
          target: point,
          sourceAnchor: anchorIndex,
          // targetAnchor: anchorIndex,
        });
        addingEdge = true;
        sourceId = nodeId;
      }
    });
  };

  const setAnchor = ({ target, type, label }) => {
    const group = target.get('group');
    const nodeId = target.getModel().id;
    // 添加自定义锚点
    if (type) {
      if (type === 'switch') {
        addAnchor(group, 0, -36, nodeId, 0);
        addAnchor(group, -96, 0, nodeId, 1);
        addAnchor(group, 96, 0, nodeId, 2);
      } else {
        addAnchor(group, 0, -36, nodeId, 0);
        addAnchor(group, 0, 36, nodeId, 1);
      }
    }

    if (label) {
      if (label === '流程开始') {
        addAnchor(group, 0, 24, nodeId, 0);
      } else if (label === '流程结束') {
        addAnchor(group, 0, -24, nodeId, 0);
      }
    }
  }

  // 新节点id
  const setNodeId = (nodes, id) => {
    if (nodes.findIndex((item) => item.id === `uuid${id}`) === -1) return `uuid${id}`;
    setNodeId(nodes, id + 1);
  }

  const dropNode = (evt, data) => {
    if (evt.originalEvent.dataTransfer && evt.originalEvent.dataTransfer.getData('type')) {
      const type = evt.originalEvent.dataTransfer.getData('type');
      const nodes = data.nodes;

      // 制造节点id
      const uuid = setNodeId(nodes, nodes.length);
      const label = type === 'switch' ? '条件分支' :  type === 'app' ? 'APP 动作' : '执行脚本';

      const node = {
        // id: String(nodes.length), //id必须为string
        id: uuid, //id必须为string
        label,
        type: type === 'switch' ? 'diamond' : 'modelRect',
        nodeType: type,
        anchorPoints: type === 'switch' ? [
          [0.5, 0], [0, 0.5], [1, 0.5]
        ] : [
            [0.5, 0, { id: 'a', shape: 'in', style: { stroke: 'red', fill: 'white' } }], [0.5, 1, { id: 'b', shape: 'out', style: { stroke: 'red', fill: 'white' } }]
          ],
        linkPoints: type === 'switch' && {
          top: true,
          bottom: false,
          left: true,
          right: true,
        },
        // description: 'description, hidden when undefined',
        x: evt.x,
        y: evt.y,
        size: [192, 72],
      }
      // graph添加数据
      graph.addItem('node', node);
      // 获取刚刚添加的node实例
      // const target = graph.findById(String(nodes.length));
      const target = graph.findById(uuid);
      setAnchor({ target, type });
      // graph.changeData(data);
      // graph.refresh();
      // graph.render();
      // 更新数据
      nodes.push(node);
      graph.data(data);
    }
  }

  React.useEffect(() => {
    const width = Ref.current.scrollWidth;
    const height = Ref.current.scrollHeight || 500;

    const minimap = new G6.Minimap({
      size: [94, 119],
      className: styles.minimap
    });

    const contextMenu = new G6.Menu({
      getContent(evt) {
        // let header;
        // if (evt.target && evt.target.isCanvas && evt.target.isCanvas()) {
        //   header = 'Canvas ContextMenu';
        // } else if (evt.item) {
        //   const itemType = evt.item.getType();
        //   header = `${itemType.toUpperCase()} ContextMenu`;
        // }
        return '删除此连接';
      },
      handleMenuClick: (target, item) => {
        graph.removeItem(item);
      },
      offsetX: 10,
      offsetY: 0,
      itemTypes: ['edge'],
      className: styles.contextmenu
    });

    graph = new G6.Graph({
      container: 'container',
      width: width,
      height: height,
      /* translate the graph to align the canvas's center, support by v3.5.1 */
      fitCenter: true,
      modes: {
        /* behavior */
        default: ['drag-canvas', 'drag-node', 'zoom-canvas'],
      },
      plugins: [minimap, !disable && contextMenu],
      defaultNode: {
        type: 'ellipse',
        size: [96, 48],
        style: {
          radius: 4,
          stroke: '#181C25',
          fill: '#262E3C',
          lineWidth: 1,
          fillOpacity: 1,
        },
        labelCfg: {
          style: {
            fill: '#E7EFFF',
            fontSize: 14,
          },
          offset: 30,
        },
        preRect: {
          show: false,
        },
        linkPoints: {
          top: true,
          bottom: true,
          fill: '#5E728C',
          stroke: '#5E728C',
        },
        logoIcon: {
          // whether to show the icon
          show: true,
          x: 0,
          y: 0,
        },
        stateIcon: {
          show: false,
        },
        icon: {}
      },
      defaultEdge: {
        // type: 'polyline',
        type: 'cubic-vertical',
        /* configure the bending radius and min distance to the end nodes */
        style: {
          radius: 10,
          offset: 30,
          endArrow: true,
          /* and other styles */
          stroke: '#5E728C',
          lineWidth: 2,
          cursor: 'pointer',
        },
      },
      nodeStateStyles: {
        hover: {
          fill: '#404B5E',
          cursor: 'pointer',
        },
      },
      /* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
      edgeStateStyles: {
        // edge style of active state
        active: {
          // opacity: 0.5,
          stroke: '#5E728C',
          lineWidth: 2,
        },
        // edge style of selected state
        selected: {
          stroke: '#5E728C',
          shadowBlur: 1,
          shadowColor: '#FFFFFF',
          lineWidth: 2,
        },
      },
    });

    // 放置节点
    graph.on('drop', (evt) => {
      dropNode(evt, data);
    })

    graph.on('mousemove', (evt) => {
      // console.log(addingEdge, edge, point);
      const point = { x: evt.x, y: evt.y };
      if (addingEdge && edge) {
        // 更新边的结束点位置为当前鼠标位置
        graph.updateItem(edge, {
          target: point,
        });
      }
    })

    graph.on('node:click', (evt) => {
      const { item } = evt;
      handleNodeClick(item);
    });

    graph.on('node:mouseenter', (evt) => {
      const { item } = evt;
      graph.setItemState(item, 'hover', true);
    });

    graph.on('node:mouseleave', (evt) => {
      const { item } = evt;
      graph.setItemState(item, 'hover', false);
    });

    graph.on('node:dragend', (evt) => {
      const { item } = evt;
      handleDragNode(item);
    })

    graph.on('edge:mouseenter', (evt) => {
      const { item } = evt;
      graph.setItemState(item, 'active', true);
    });

    graph.on('edge:mouseleave', (evt) => {
      const { item } = evt;
      graph.setItemState(item, 'active', false);
    });

    graph.on('edge:click', (evt) => {
      const { item } = evt;
      // 拖拽过程中，点击会点击到新增的边上
      if (addingEdge && edge == item) {
        graph.removeItem(edge);
        edge = null;
        addingEdge = false;
        sourceId = null;
      } else {
        graph.setItemState(item, 'selected', true);
      }
    });

    graph.on('canvas:click', (evt) => {
      graph.getEdges().forEach((edge) => {
        graph.clearItemStates(edge);
      });
      setVisible(false);
    });

    // 使连线不重叠
    graph.on('aftercreateedge', (e) => {
      const edges = graph.save().edges;
      G6.Util.processParallelEdges(edges);
      graph.getEdges().forEach((edge, i) => {
        graph.updateItem(edge, edges[i]);
      });
    });

  }, []);

  React.useEffect(() => {
    if (task) {
      // setNodes(task);
      const { nodes, edges } = task;
      // setData({ nodes: [...nodes], edges: [...edges] })
      data.nodes = [...nodes];
      data.edges = [...edges];
      graph.read({ ...data, nodes, edges });
      setEdgesInfo(edges);

      if (!disable) {
        nodes.forEach(item => {
          // 获取刚刚添加的node实例
          const target = graph.findById(item.id);
          setAnchor({ target, type: item.nodeType, label: item.label });
        });
      }

      setGraphAction({
        zoomIn: () => { graph.zoom(1.20, { x: 0, y: 0 }); },
        zoomOut: () => { graph.zoom(0.8, { x: 0, y: 0 }); },
        focusItem: () => {
          if (nodes && nodes.length) {
            if (nodes.length === 1) {
              graph.focusItem(nodes[0].id);
            } else {
              const node = nodes.find(item => item.label === '流程开始');
              if (node) {
                graph.focusItem(node.id);
              }
            }
          }
        }
      })

      // 重新绑定事件
      graph.off('drop');
      graph.on('drop', (evt) => {
        dropNode(evt, data);
      });
    }
  }, [id]);

  return (
    <div id="container" ref={Ref} style={{ height: 'calc(100% - 64px)' }} onDragOver={(e) => { e.preventDefault(); }}>
    </div>
  )
};

export default PlayGraph;
